﻿namespace Probel.Client
{
    using System;
    using System.ComponentModel;
    using System.Configuration;
    using System.Linq;
    using System.Reflection;

    using Probel.Client.Commands;
    using Probel.Client.StatLoggerReference;
    using Probel.Client.StatReaderReference;
    using Probel.Statistics.Helpers;

    class Program
    {
        #region Fields

        static readonly Input Input = new Input();
        private static readonly string[] QuitCommands = new string[] { "quit", "exit", "bye" };

        #endregion Fields

        #region Methods

        private static bool Execute(string cmd, StatLoggerClient proxyLogger, StatReaderClient proxyReader)
        {
            var @namespace = "Probel.Client.Commands";
            var fullCommand = GetCommand(cmd);

            var type = (from t in Assembly.GetExecutingAssembly().GetTypes()
                        where t.IsClass && t.Namespace == @namespace
                        && (from a in t.GetCustomAttributes<CommandAttribute>()
                            where a.Name.ToLower() == fullCommand.Command.ToLower()
                               || a.ShortName.ToLower() == fullCommand.Command.ToLower()
                            select a).Count() > 0
                        select t).FirstOrDefault();

            if (type != null)
            {
                var instance = Activator.CreateInstance(type) as ICommand;
                if (instance is ICommand)
                {
                    var command = instance as ICommand;
                    try
                    {
                        command.Execute(new { Input = Input, ProxyLogger = proxyLogger, ProxyReader = proxyReader, Arguments = fullCommand.Arguments });
                    }
                    catch (Exception ex) { ShowError(ex); }

                    return true;
                }
                else { return false; }
            }
            else { return false; }
        }

        private static dynamic GetCommand(string cmd)
        {
            var elements = cmd.Split('-');

            if (elements.Count() == 0) { throw new ArgumentException(string.Format("The command '{0}' is malformed", cmd)); }

            var args = elements.Skip(1)
                               .Take(elements.Length - 1)
                               .ToArray();

            return new
            {
                Command = elements[0].Trim(),
                Arguments = args,
            };
        }

        static void Main(string[] args)
        {
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("Client for NDoctor statistics");
            Console.WriteLine();
            Console.ResetColor();

            var cmd = string.Empty;
            using (var proxy = new StatLoggerClient("Logger"))
            using (var proxyreader = new StatReaderClient("Reader"))
            {
                do
                {
                    cmd = Input.Read("> ", ConsoleColor.Yellow);
                    if (!Execute(cmd, proxy, proxyreader) && !QuitCommands.Contains(cmd))
                    {
                        Console.WriteLine("Unknown command...");
                    }
                } while (!QuitCommands.Contains(cmd));
            }
        }

        private static void ShowError(Exception ex)
        {
            Console.WriteLine();
            Console.ForegroundColor = ConsoleColor.Red;
            var verbose = bool.Parse((ConfigurationManager.AppSettings["verbose"]));

            var msg = (verbose) ? ex.ToString()
                                : ex.Message;
            Console.WriteLine(msg);
            Console.ResetColor();
        }

        #endregion Methods
    }
}